package com.nexgo.payment.action.online.upload;

import com.nexgo.payment.constrant.PreferencesConstants;
import com.nexgo.payment.constrant.TransType;
import com.nexgo.payment.constrant.UploadState;
import com.nexgo.payment.databases.DataSource;
import com.nexgo.payment.databases.TransRecord;
import com.nexgo.payment.entity.MessageData;
import com.nexgo.payment.entity.TransData;
import com.nexgo.payment.util.StringUtils;
import com.nexgo.payment.util.TransUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * Created by xiaox on 2017/9/14.
 */

/**
 * 所有脱机上送的父级
 */
abstract class AbsUploadOffline extends Upload {
    private final Logger log;
    private OnUploadListener mListener;
    private TransRecord mTransRecord;
    private boolean mForceBreak;
    private final List<TransRecord> mTransRecords;
    private int mIdx = 0;

    AbsUploadOffline(DataSource repository) {
        super(repository);
        log = LoggerFactory.getLogger(getClass().getSimpleName());
        mTransRecords = getOfflineTransRecords();
    }

    /**
     * 获取上送列表
     *
     * @return
     */
    abstract List<TransRecord> getOfflineTransRecords();

    /**
     * 批上送类型
     *
     * @return
     */
    abstract TransType getTransType();

    /**
     * UI提示语
     *
     * @return
     */
    abstract String getTip();

    @Override
    TransData buildTransData() {
        TransData transData = new TransData();
        transData.setTransType(getTransType());
        transData.setOrgTraceNum(mTransRecord.getTraceNum());
        return transData;
    }

    @Override
    public void sendTrans(OnUploadListener listener) {
        mListener = listener;
        sendOrComplete();
    }

    @Override
    void onTransResponseCheckError(String responseCode) {
        if (TransUtils.isNeedReLogin(responseCode)) {
            mRepository.setParamValue(PreferencesConstants.IS_NEED_LOGIN, "1");
            mRepository.syncParamValue();
            //强制退出
            mForceBreak = true;
        } else if (TransUtils.isRepeatedTrans(responseCode)) {
            log.debug("重复上送，置为成功");
            //重复上送
            updateTransRecordUploadState(UploadState.OFFLINE_UPLOAD_SUCCESSFUL);
        } else {
            log.debug("上送被拒");
            //被拒
            updateTransRecordUploadState(UploadState.OFFLINE_UPLOAD_REJECTED);
        }
    }

    @Override
    void onTransResponse(MessageData messageData) {
        updateTransRecordUploadState(UploadState.OFFLINE_UPLOAD_SUCCESSFUL);
    }

    @Override
    void onTransTimeout() {
        //超过最大上送次数当失败处理
        if (isOverMaxReUploadTimes()) {
            updateTransRecordUploadState(UploadState.OFFLINE_UPLOAD_FAILED);
        }
        sendOrComplete();
    }

    @Override
    void onTransFailed() {
        mListener.onUploadFailed();
    }

    @Override
    void onTransComplete() {
        if (mForceBreak) {
            onTransFailed();
        } else {
            sendOrComplete();
        }
    }

    @Override
    public boolean isOverMaxReUploadTimes() {
        return sUploadCounter >= getMaxReUploadTimes();
    }

    private int getMaxReUploadTimes() {
        return Integer.parseInt(StringUtils.firstNonEmpty(mRepository.getParamValue(PreferencesConstants.OFFLINE_TRANS_UPLOAD_TIMES), "3"));
    }

    private void sendOrComplete() {
        if (hasNext()) {
            log.debug("存在需要上送的交易{}", getTransType());
            mListener.onShowTip(getTip());
            send();
        } else {
            log.debug("上送结束", getTransType());
            mListener.onUploadComplete();
        }
    }

    private boolean hasNext() {
        if (mTransRecords == null) {
            return false;
        }
        for (int i = mIdx; i < mTransRecords.size(); i++) {
            TransRecord transRecord = mTransRecords.get(i);
            //已成功的跳过
            if (transRecord.getIsBatchUpload()) {
                continue;
            }
            mIdx = i + 1;
            mTransRecord = transRecord;
            return true;
        }
        return false;
    }

    private void updateTransRecordUploadState(UploadState state) {
        log.debug("更新上送状态 {}", state);
        mTransRecord.setUploadState(state.ordinal());
        mRepository.updateTransRecord(mTransRecord);
    }
}
